﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;

namespace Felbot.IO {
    /// <summary>
    /// Allows manipulation of a .ini-style configuration file. Can handle a "global" file.
    /// </summary>
    public class INIControl {
        private string m_Path;
        private INIControl m_Global;
        private Dictionary<string, Dictionary<string, string>> m_Settings = new Dictionary<string, Dictionary<string, string>>();

        /// <summary>
        /// Gets or sets the path to the INI file. Setting this will MOVE the file!
        /// </summary>
        public string Path {
            set {
                try {
                    File.Move(m_Path, value);
                } catch (IOException e) {
                    if (MessageBox.Show("File.Move() Exception:\r\n" +
                                        e.ToString(),
                                        "Felbot",
                                        MessageBoxButtons.RetryCancel,
                                        MessageBoxIcon.Exclamation)
                            == DialogResult.Retry) {
                        Path = value;
                        return;
                    }
                }
                m_Path = value;
            }
            get {
                return m_Path;
            }
        }

        /// <summary>
        /// Creates a new INIControl class, also CREATES an INI-style Felbot file!
        /// </summary>
        /// <param name="a_sPath">The path to the file.</param>
        /// <param name="a_icGlobal">The global profile INIControl.</param>
        public INIControl(string path, INIControl global) {
            m_Global = global;
            m_Path = path;
            if (!Directory.Exists(new FileInfo(path).DirectoryName)) {
                try {
                    Directory.CreateDirectory(new FileInfo(path).DirectoryName);
                } catch (IOException e) {
                    MessageBox.Show("Directory.CreateDirectory() Exception:\r\n" +
                                    e.ToString(),
                                    "Felbot",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Exclamation);
                    return;
                }
            }
            if (!File.Exists(path)) {
                try {
                    File.CreateText(path).Dispose();
                } catch (IOException e) {
                    MessageBox.Show("File.CreateText() Exception:\r\n" +
                                    e.ToString(),
                                    "Felbot",
                                    MessageBoxButtons.OK,
                                    MessageBoxIcon.Exclamation);
                    return;
                }
            } else {
                LoadSettings(); // only load the settings if we know we didn't just create it (or risk File.ReadAllLines() exception!).
            }
        }

        /// <summary>
        /// Load the settings from the file.
        /// </summary>
        public void LoadSettings() {
            try {
                string section = "GENERAL", setting = null, value = null;
                string[] keyValuePair;
                string[] contents = File.ReadAllLines(m_Path, Encoding.UTF8);
                foreach (string line in contents) {
                    if (line.Trim().StartsWith("[") && line.Trim().EndsWith("]")) {
                        section = line.Substring(1, line.Length - 2).Trim().ToUpper();
                    } else if (line.Trim().Length > 0 && "abcdefghijklmnopqrstuvwxyz_".Contains(line.Trim()[0].ToString().ToLower()) && line.Contains("=")) {
                        if (!m_Settings.ContainsKey(section.ToUpper())) {
                            m_Settings.Add(section.ToUpper(), new Dictionary<string, string>());
                        }

                        keyValuePair = line.Split(new string[] { "=" }, 2, StringSplitOptions.None);
                        setting = keyValuePair[0].Trim();
                        value = keyValuePair[1].Trim().Replace(@"\\", "\x00").Replace(@"\nl", Environment.NewLine).Replace("\x00", @"\\");

                        if (m_Settings[section.ToUpper()].ContainsKey(setting))
                            m_Settings[section.ToUpper()][setting] = value;
                        else
                            m_Settings[section.ToUpper()].Add(setting, value);
                    }
                }
            } catch (Exception e) {
                if (MessageBox.Show("File.ReadAllLines() Exception:\r\n" +
                                    e.ToString(),
                                    "Felbot",
                                    MessageBoxButtons.RetryCancel,
                                    MessageBoxIcon.Exclamation)
                        == DialogResult.Retry) {
                    LoadSettings();
                }
            }
        }

        /// <summary>
        /// Save the settings to the file.
        /// </summary>
        public void SaveSettings() {
            try {
                string newContents = "";
                foreach (KeyValuePair<string, Dictionary<string, string>> section in m_Settings) {
                    newContents += "[" + section.Key + "]" + Environment.NewLine;
                    foreach (KeyValuePair<string, string> m_sSetting in section.Value) {
                        newContents += m_sSetting.Key + "=" + m_sSetting.Value.Replace(@"\\", "\x00").Replace(Environment.NewLine, "\nl").Replace("\x00", @"\\") + Environment.NewLine;
                    }
                    newContents += Environment.NewLine;
                }
                File.WriteAllText(m_Path, newContents, Encoding.UTF8);
            } catch (IOException e) {
                if (MessageBox.Show("File.WriteAllText() Exception:\r\n" +
                                    e.ToString(),
                                    "Felbot",
                                    MessageBoxButtons.RetryCancel,
                                    MessageBoxIcon.Exclamation)
                        == DialogResult.Retry) {
                    SaveSettings();
                }
            }
        }

        /// <summary>
        /// Sets a setting in the file.
        /// </summary>
        /// <param name="a_sSection">Section name.</param>
        /// <param name="a_sSetting">Setting name.</param>
        /// <param name="a_sNewValue">New value.</param>
        /// <returns>Whether operation succeeded.</returns>
        public bool SetSetting(string section, string setting, Setting newValue) {
            return SetSetting(section, setting, newValue, true);
        }

        /// <summary>
        /// Sets a setting in the file.
        /// </summary>
        /// <param name="a_sSection">Section name.</param>
        /// <param name="a_sSetting">Setting name.</param>
        /// <param name="a_sNewValue">New value.</param>
        /// <param name="a_bOverwrite">True to overwrite the current value.</param>
        /// <returns>Whether operation succeeded.</returns>
        public bool SetSetting(string section, string setting, Setting newValue, bool overwrite) {
            string trimmedSection = section.Trim().ToUpper();
            string trimmedSetting = setting.Trim();
            string trimmedValue = newValue.ToString("").Trim();
            if (m_Settings.ContainsKey(trimmedSection)) {
                if (m_Settings[trimmedSection].ContainsKey(trimmedSetting)) {
                    if (overwrite) {
                        if (trimmedValue != "")
                            m_Settings[trimmedSection][trimmedSetting] = trimmedValue;
                        return true;
                    } else {
                        return false;
                    }
                } else {
                    if (trimmedValue != "")
                        m_Settings[trimmedSection].Add(trimmedSetting, trimmedValue);
                    return true;
                }
            } else {
                m_Settings.Add(trimmedSection, new Dictionary<string, string>());
                m_Settings[trimmedSection].Add(trimmedSetting, trimmedValue);
                return true;
            }
        }

        /// <summary>
        /// Gets a setting from the file.
        /// </summary>
        /// <param name="a_sSection">Section name.</param>
        /// <param name="a_sSetting">Setting name.</param>
        /// <returns>The setting as a Setting object.</returns>
        public Setting GetSetting(string section, string setting) {
            string global = null;
            if (m_Global != null) //this is the global profile
                global = m_Global.GetSetting(section, setting).ToString();
            string trimmedSection = section.Trim().ToUpper();
            string trimmedSetting = setting.Trim();
            string trimmedValue = setting.Trim();
            if (m_Settings.ContainsKey(trimmedSection)) {
                if (m_Settings[trimmedSection].ContainsKey(trimmedSetting)) {
                    return new Setting(m_Settings[trimmedSection][trimmedSetting], global);
                } else {
                    return new Setting(null, global);
                }
            } else {
                return new Setting(null, global);
            }
        }

        /// <summary>Deletes the file this INIControl is associated with.</summary>
        public void Delete() {
            try {
                File.Delete(m_Path);
            } catch (IOException e) {
                if (MessageBox.Show("File.Delete() Exception:\r\n" +
                                    e.ToString(),
                                    "Felbot",
                                    MessageBoxButtons.RetryCancel,
                                    MessageBoxIcon.Exclamation)
                        == DialogResult.Retry) {
                    Delete();
                }
            }
        }
    }
}
